package com.ruoyi.activiti.controller;

import com.ruoyi.activiti.domain.dto.ActivitiHighLineDTO;
import com.ruoyi.activiti.service.IActivitiHistoryService;
import com.ruoyi.activiti.service.IProcessImageService;
import com.ruoyi.activiti.utils.ActivitiUtils;
import com.ruoyi.activiti.utils.DefaultProcessDiagramGenerator;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/hello")
public class ActivitiImageController {
    protected final Logger logger = LoggerFactory.getLogger(ActivitiImageController.class);
    @Autowired
    private IActivitiHistoryService activitiHistoryService;
    @Autowired
    private IProcessImageService processImageService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;


    //流程图高亮
    @GetMapping("/gethighLine")
    public String gethighLine(@RequestParam("instanceId") String instanceId) {
        return activitiHistoryService.gethighLine2(instanceId);
    }

    @GetMapping("/gethighLine2")
    public void gethighLine2( @RequestParam("instanceId") String instanceId,HttpServletResponse response) throws IOException {
        activitiHistoryService.gethighLine3(instanceId,response);
    }
    /**
     * 根据流程定义id查看流程图
     *
     * @param instanceId
     * @return
     */
    @GetMapping(value = "/draw")
    //@ApiOperation(value = "根据流程定义id查看流程图", notes = "根据流程定义id，查询返回不带节点流转信息的图片")
    public void image(@RequestParam("instanceId") String instanceId,@RequestParam("procInstId") String procInstId, HttpServletResponse response) throws Exception {

       /* try (OutputStream out = response.getOutputStream();
             InputStream is = activitiHistoryService.getFlowImgByProcInstId(instanceId, null, false)) {
            if (null != is) {
                BufferedImage image = ImageIO.read(is);
                response.setContentType("image/png");
                ImageIO.write(image, "png", out);
            }
        } catch (Exception ex) {
            logger.error("查看流程图失败", ex);
        }*/
       //第二种
        try (OutputStream out = response.getOutputStream();
             InputStream is = activitiHistoryService.getFlowImgByProcInstId(instanceId, procInstId, false)) {
            // 输出图片内容
            Integer byteSize = 1024;
            byte[] b = new byte[byteSize];
            int len;
            while ((len = is.read(b, 0, byteSize)) != -1) {
                out.write(b, 0, len);
            }
            String imageName = "D:\\jk_workspace\\activiti\\image" + Instant.now().getEpochSecond()+".png";
            FileUtils.copyInputStreamToFile(is, new File(imageName));
        } catch (Exception ex) {
            logger.error("查看流程图失败", ex);
        }

//       return activitiHistoryService.getFlowImgByProcInstId(instanceId, null, false);
    }


    //http://localhost:81/dev-api/hello/draw2?instanceId=leave:1:757c8736-f138-11eb-a3e5-005056c00008&procInstId=ba374907-f138-11eb-a3e5-005056c00008
    @GetMapping("/draw2")
    public void processImageGet(@RequestParam("instanceId") String instanceId,@RequestParam("procInstId") String procInstId, HttpServletResponse response){
        try {
            InputStream img = activitiHistoryService.getFlowImgByProcInstId(instanceId,procInstId,true);
            byte[] bytes = IOUtils.toByteArray(img);
            response.setContentType("image/svg+xml");
            OutputStream outputStream = response.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成流程图
     * @param procInstId 流程实例ID
     * @param httpServletResponse response entity
     */
    @GetMapping("/draw3")
    public void processImageGet3(@RequestParam("procInstId") String procInstId, HttpServletResponse httpServletResponse){
        try {
            InputStream img = processImageService.getFlowImgByProcInstId(procInstId);
            byte[] bytes = IOUtils.toByteArray(img);
            httpServletResponse.setContentType("image/svg+xml");
            OutputStream outputStream = httpServletResponse.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成流程图
     * @param procInstId 流程实例ID
     * @param httpServletResponse response entity
     */
    @GetMapping("/draw4")
    public void processImageGet4(@RequestParam("procInstId") String procInstId, HttpServletResponse httpServletResponse){
        try {
            InputStream img = processImageService.getFlowImgByProcInstId2(procInstId);
            byte[] bytes = IOUtils.toByteArray(img);
            httpServletResponse.setContentType("image/svg+xml");
            OutputStream outputStream = httpServletResponse.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * localhost:81/dev-api/hello/draw5?procInstId=ac5d0fd6-f299-11eb-a6ce-005056c00008
     * @param procInstId
     * @param httpServletResponse
     */
    @GetMapping("/draw5")
    public void processImageGet5(@RequestParam("procInstId") String procInstId, HttpServletResponse httpServletResponse){
        try {
            InputStream img = processImageService.getProcessDiagram(procInstId);
            String imageName = "image" + Instant.now().getEpochSecond()+".png";
            logger.debug("图片生成中。。。。"+imageName);
            FileUtils.copyInputStreamToFile(img, new File("src/main/resources/"+imageName));


            byte[] bytes = IOUtils.toByteArray(img);
            httpServletResponse.setContentType("image/png");
            OutputStream outputStream = httpServletResponse.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * <p>输出图像</p>
     * @param response 响应实体
     * @param bpmnModel 图像对象
     * @param flowIds 已执行的线集合
     * @param executedActivityIdList void 已执行的节点ID集合
     * @author 悟纤【公众号SpringBoot】
     */
    private void outputImg(HttpServletResponse response, BpmnModel bpmnModel, List<String> flowIds, List<String> executedActivityIdList) {
        InputStream imageStream = null;
        // import org.activiti.image.impl.DefaultProcessDiagramGenerator;
        ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        response.setContentType("image/svg+xml");
        try {
            imageStream = processDiagramGenerator.generateDiagram(bpmnModel, executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", true, "png");
            // 输出资源内容到相应对象
            byte[] b = new byte[1024];
            int len;
            while ((len = imageStream.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
            response.getOutputStream().flush();
        }catch(Exception e) {
            e.printStackTrace();
        } finally { // 流关闭
            if(imageStream != null){
                try {
                    imageStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * <p>查看当前流程图</p>
     * @param instanceId 流程实例
     * @param response void 响应
     * @author 悟纤【公众号SpringBoot】
     */
    @ResponseBody
    @RequestMapping(value="/showImg2021")
    public void showImg(String instanceId, HttpServletResponse response) {
        /*
         * 参数校验
         */
        System.out.println("查看完整流程图！流程实例ID:"+instanceId);
        if(StringUtils.isBlank(instanceId)) return;


        /*
         *  获取流程实例
         */
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        if(processInstance == null) {
            System.out.println("流程实例ID:"+instanceId+"没查询到流程实例！");
            return;
        }

        // 根据流程对象获取流程对象模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());


        /*
         *  查看已执行的节点集合
         *  获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
         */
        // 构造历史流程查询
        HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId);
        // 查询历史节点
        List<HistoricActivityInstance> historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
        if(historicActivityInstanceList == null || historicActivityInstanceList.size() == 0) {
            System.out.println("流程实例ID:"+instanceId+"没有历史节点信息！");
            outputImg(response, bpmnModel, null, null);
            return;
        }
        // 已执行的节点ID集合(将historicActivityInstanceList中元素的activityId字段取出封装到executedActivityIdList)
        List<String> executedActivityIdList = historicActivityInstanceList.stream().map(item -> item.getActivityId()).collect(Collectors.toList());

        /*
         *  获取流程走过的线
         */
        // 获取流程定义
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
        List<String> flowIds = ActivitiUtils.getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList);


        /*
         * 输出图像，并设置高亮
         */
        outputImg(response, bpmnModel, flowIds, executedActivityIdList);
    }


}
